package com.orionlily.redis3t.zkcurator;

import com.orionlily.redis3t.entity.User;
import com.orionlily.redis3t.service.UserService;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * zk 分布式锁使用curator
 *
 * @author li.lc
 */
@RequestMapping("/curator")
@RestController
public class CuratorDistributeLockController {

    @Resource(name = "curatorFramework")
    private CuratorFramework curatorFramework;

    @Resource(name = "userService")
    private UserService userService;

    @Resource(name = "redisTemplate")
    private RedisTemplate redisTemplate;

    /**
     * 父节点位置，永久节点
     */
    private static final String PARENT_PATH = "/distribute";

    /**
     * 临时节点位置
     */
    private static final String CHILD_PATH = "/zkLock";

    /**
     * 使用redisson
     */
    @GetMapping("/zkLock/{id}")
    public void getKeyWithCurator(@PathVariable Long id) {
        InterProcessMutex rlock = null;
        try {
            Stat stat = curatorFramework.checkExists().forPath(PARENT_PATH);
            if (stat == null) {
                curatorFramework.create().withMode(CreateMode.PERSISTENT).forPath(PARENT_PATH);
            }

            rlock = new InterProcessMutex(curatorFramework, PARENT_PATH + CHILD_PATH);

            if (rlock.acquire(10L, TimeUnit.SECONDS)) {

                Object value = redisTemplate.opsForValue().get("llc" + id.toString());
                if (Objects.nonNull(value)) {
                    System.out.println(System.currentTimeMillis()+"------------"+ Thread.currentThread()
                            + "-------在缓存查询到id=" + id + "的值=" + value.toString());
                    return;
                }

                User user = userService.queryById(id);
                if (Objects.nonNull(user)) {
                    redisTemplate.opsForValue().set("llc" + id.toString(), user, 30, TimeUnit.MINUTES);
                    System.out.println(System.currentTimeMillis()+"------------"+ Thread.currentThread()
                            + "-------在数据库查询到id=" + id + "的值=" + user);
                    return;
                }
            }
            System.out.println(System.currentTimeMillis()+"------------"+ Thread.currentThread()
                    + "-------10s也拿不到锁");
            return;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (rlock != null) {
                    rlock.release();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @GetMapping("/crt")
    public void getKeyWithCurator222() throws Exception {
        curatorFramework.create().withMode(CreateMode.PERSISTENT).forPath("/abc");
    }
}
